import { arrayFill } from '../../Source/Cesium.js';
import { Cartesian3 } from '../../Source/Cesium.js';
import { EllipsoidOutlineGeometry } from '../../Source/Cesium.js';
import { GeometryOffsetAttribute } from '../../Source/Cesium.js';
import { Math as CesiumMath } from '../../Source/Cesium.js';
import createPackableSpecs from '../createPackableSpecs.js';

describe('Core/EllipsoidOutlineGeometry', function() {

    it('constructor throws if stackPartitions less than 1', function() {
        expect(function() {
            return new EllipsoidOutlineGeometry({
                stackPartitions: 0
            });
        }).toThrowDeveloperError();
    });

    it('constructor throws if slicePartitions less than 0', function() {
        expect(function() {
            return new EllipsoidOutlineGeometry({
                slicePartitions: -1
            });
        }).toThrowDeveloperError();
    });

    it('constructor throws if subdivisions less than 0', function() {
        expect(function() {
            return new EllipsoidOutlineGeometry({
                subdivisions: -2
            });
        }).toThrowDeveloperError();
    });

    it('constructor throws if offset attribute is equal to GeometryOffsetAttribute.TOP', function () {
        expect(function() {
            return new EllipsoidOutlineGeometry({
                offsetAttribute: GeometryOffsetAttribute.TOP
            });
        }).toThrowDeveloperError();
    });

    it('constructor rounds floating-point slicePartitions', function() {
        var m = new EllipsoidOutlineGeometry({
            slicePartitions: 3.5,
            stackPartitions: 3,
            subdivisions: 3
        });
        expect(m._slicePartitions).toEqual(4);
    });

    it('constructor rounds floating-point stackPartitions', function() {
        var m = new EllipsoidOutlineGeometry({
            slicePartitions: 3,
            stackPartitions: 3.5,
            subdivisions: 3
        });
        expect(m._stackPartitions).toEqual(4);
    });

    it('constructor rounds floating-point subdivisions', function() {
        var m = new EllipsoidOutlineGeometry({
            slicePartitions: 3,
            stackPartitions: 3,
            subdivisions: 3.5
        });
        expect(m._subdivisions).toEqual(4);
    });

    it('computes positions', function() {
        var m = EllipsoidOutlineGeometry.createGeometry(new EllipsoidOutlineGeometry({
            stackPartitions: 3,
            slicePartitions: 3,
            subdivisions: 3
        }));

        expect(m.attributes.position.values.length).toEqual(24 * 3);
        expect(m.indices.length).toEqual(16 * 2);
        expect(m.boundingSphere.radius).toEqual(1);
    });

    it('computes positions for partial ellipsoid', function() {
        var m = EllipsoidOutlineGeometry.createGeometry(new EllipsoidOutlineGeometry({
            innerRadii: new Cartesian3(0.5, 0.5, 0.5),
            minimumClock: CesiumMath.toRadians(90.0),
            maximumClock: CesiumMath.toRadians(270.0),
            minimumCone: CesiumMath.toRadians(30.0),
            maximumCone: CesiumMath.toRadians(120.0),
            stackPartitions: 3,
            slicePartitions: 3,
            subdivisions: 3
        }));

        expect(m.attributes.position.values.length).toEqual(24 * 3);
        expect(m.indices.length).toEqual(20 * 2);
        expect(m.boundingSphere.radius).toEqual(1);
    });

    it('computes offset attribute', function() {
        var m = EllipsoidOutlineGeometry.createGeometry(new EllipsoidOutlineGeometry({
            stackPartitions : 3,
            slicePartitions: 3,
            subdivisions: 3,
            offsetAttribute: GeometryOffsetAttribute.ALL
        }));

        var numVertices = 24;
        expect(m.attributes.position.values.length).toEqual(numVertices * 3);

        var offset = m.attributes.applyOffset.values;
        expect(offset.length).toEqual(numVertices);
        var expected = new Array(offset.length);
        expected = arrayFill(expected, 1);
        expect(offset).toEqual(expected);
    });

    it('computes partitions to default to 2 if less than 2', function() {
        var geometry = new EllipsoidOutlineGeometry({
            radii: new Cartesian3(0.5, 0.5, 0.5)
        });

        geometry._slicePartitions = 0;
        geometry._stackPartitions = 0;

        var m = EllipsoidOutlineGeometry.createGeometry(geometry);

        expect(m.indices.length).toEqual(1016);
    });

    it('undefined is returned if the x, y, or z radii are equal or less than zero', function() {
        var ellipsoidOutline0 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(0.0, 500000.0, 500000.0)
        });
        var ellipsoidOutline1 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(1000000.0, 0.0, 500000.0)
        });
        var ellipsoidOutline2 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(1000000.0, 500000.0, 0.0)
        });
        var ellipsoidOutline3 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(-10.0, 500000.0, 500000.0)
        });
        var ellipsoidOutline4 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(1000000.0, -10.0, 500000.0)
        });
        var ellipsoidOutline5 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(1000000.0, 500000.0, -10.0)
        });
        var ellipsoidOutline6 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(0.0, 100000.0, 100000.0)
        });
        var ellipsoidOutline7 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(100000.0, 0.0, 100000.0)
        });
        var ellipsoidOutline8 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(100000.0, 100000.0, 0.0)
        });
        var ellipsoidOutline9 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(-10.0, 100000.0, 100000.0)
        });
        var ellipsoidOutline10 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(100000.0, -10.0, 100000.0)
        });
        var ellipsoidOutline11 = new EllipsoidOutlineGeometry({
            radii : new Cartesian3(500000.0, 500000.0, 500000.0),
            innerRadii : new Cartesian3(100000.0, 100000.0, -10.0)
        });

        var geometry0 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline0);
        var geometry1 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline1);
        var geometry2 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline2);
        var geometry3 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline3);
        var geometry4 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline4);
        var geometry5 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline5);
        var geometry6 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline6);
        var geometry7 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline7);
        var geometry8 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline8);
        var geometry9 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline9);
        var geometry10 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline10);
        var geometry11 = EllipsoidOutlineGeometry.createGeometry(ellipsoidOutline11);

        expect(geometry0).toBeUndefined();
        expect(geometry1).toBeUndefined();
        expect(geometry2).toBeUndefined();
        expect(geometry3).toBeUndefined();
        expect(geometry4).toBeUndefined();
        expect(geometry5).toBeUndefined();
        expect(geometry6).toBeUndefined();
        expect(geometry7).toBeUndefined();
        expect(geometry8).toBeUndefined();
        expect(geometry9).toBeUndefined();
        expect(geometry10).toBeUndefined();
        expect(geometry11).toBeUndefined();
    });

    var ellipsoidgeometry = new EllipsoidOutlineGeometry({
        radii : new Cartesian3(1.0, 2.0, 3.0),
        innerRadii : new Cartesian3(0.5, 0.6, 0.7),
        minimumClock : 0.1,
        maximumClock : 0.2,
        minimumCone : 0.3,
        maximumCone : 0.4,
        slicePartitions : 3,
        stackPartitions : 3,
        subdivisions: 3
    });
    var packedInstance = [
        1.0, 2.0, 3.0,
        0.5, 0.6, 0.7,
        0.1, 0.2,
        0.3, 0.4,
        3.0, 3.0, 3.0,
        -1
    ];
    createPackableSpecs(EllipsoidOutlineGeometry, ellipsoidgeometry, packedInstance);
});
